/*
DB Autobackuper plugin for Miranda IM

Copyright (C) 2005-2012 chaos.persei, sje, Kildor, Billy_Bons, Vasilich, Nikolay Raspopov

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

#include "stdafx.h"
#include "options.h"

Options options = {};
static Options new_options = {};
static HWND hPathTip = NULL;

int LoadOptions()
{
	options.backup_types = (BackupType)DBGetContactSettingByte( 0, "AutoBackups", "BackupType", (BYTE)BT_PERIODIC );
	options.period = max( 1, min( 60, (unsigned int)DBGetContactSettingWord( 0, "AutoBackups", "Period", 1 ) ) );
	options.period_type = max( PT_DAYS , min( PT_MINUTES, (PeriodType)DBGetContactSettingByte( 0, "AutoBackups", "PeriodType", (BYTE)PT_DAYS ) ) );
	options.num_backups = max( 1, min( 100, (unsigned int)DBGetContactSettingWord( 0, "AutoBackups", "NumBackups", 3 ) ) );
	options.disable_popups = (BOOL)DBGetContactSettingByte( 0, "AutoBackups", "NoPopups", 0 );

	if ( ServiceExists( MS_FOLDERS_GET_PATH ) ) 
	{
		FoldersGetCustomPathT( hFolder, options.folder, MAX_PATH, DIR SUB_DIR );
	}
	else
	{
		_tcscpy_s( options.folder, MAX_PATH, DIR SUB_DIR );
		DBVARIANT dbv = {};
		if ( ! DBGetContactSettingTString( 0, "AutoBackups", "Folder", &dbv ) )
		{
			LPCTSTR tmp = Utils_ReplaceVarsT( dbv.ptszVal );
			if ( *tmp )
			{
				if ( _tcslen( tmp ) >= 2 && ( tmp[1] == ':' || ( tmp[0] == '\\' && tmp[1] == '\\' ) ) )
					_tcsncpy_s( options.folder, MAX_PATH, dbv.ptszVal, MAX_PATH - 1 );
				else
					mir_sntprintf( options.folder, MAX_PATH, _T("%s\\%s"), _T("%miranda_profile%"), dbv.ptszVal );
			}
			mir_free( (void*)tmp);
			DBFreeVariant(&dbv);
		}
	}

	SaveOptions();

	return 0;
}

static LPCTSTR szShortenDirs[] =
{
	_T("%miranda_userdata%"),
	_T("%miranda_profile%"),
	_T("%miranda_path%"),
	_T("%miranda_logpath%"),
	_T("%miranda_avatarcache%"),
	_T("%mydocuments%"),
	_T("%desktop%"),
	_T("%appdata%"),
	_T("%localappdata%"),
	_T("%userprofile%"),
	_T("%programfiles%"),
	_T("%allusersprofile%"),
	_T("%temp%"),
	_T("%systemroot%"),
	_T("%systemdrive%"),
	NULL
};

void ShortenPath(LPTSTR szFolder)
{
	PathRemoveBackslash( szFolder );

	for ( int i = 0; szShortenDirs[ i ]; ++i )
	{
		LPCTSTR tmp = Utils_ReplaceVarsT( szShortenDirs[ i ] );
		if ( *tmp && *tmp != _T('%') )
		{
			size_t tmp_len = _tcslen( tmp );
			size_t opt_len = _tcslen( szFolder );
			if ( opt_len >= tmp_len &&
				_tcsnicmp( tmp, szFolder, tmp_len ) == 0 &&
				( szFolder[ tmp_len ] == _T('\\') || szFolder[ tmp_len ] == _T('\0') ) )
			{
				TCHAR short_folder[ MAX_PATH ];
				_tcsncpy_s( short_folder, MAX_PATH, szFolder + tmp_len, MAX_PATH - 1 );
				
				_tcscpy_s( szFolder, MAX_PATH, szShortenDirs[ i ] );
				_tcscat_s( szFolder, MAX_PATH, short_folder );			

				mir_free( (void*)tmp );
				break;
			}
		}
		mir_free( (void*)tmp );
	}
}

int SaveOptions()
{
	ShortenPath( options.folder );

	DBWriteContactSettingTString( 0, "AutoBackups", "Folder", options.folder );
	DBWriteContactSettingByte( 0, "AutoBackups", "BackupType", (BYTE)options.backup_types );
	DBWriteContactSettingWord( 0, "AutoBackups", "Period", (WORD)options.period );
	DBWriteContactSettingByte( 0, "AutoBackups", "PeriodType", (BYTE)options.period_type );
	DBWriteContactSettingWord( 0, "AutoBackups", "NumBackups", (WORD)options.num_backups );
	DBWriteContactSettingByte( 0, "AutoBackups", "NoPopups", (BYTE)options.disable_popups );

	return 0;
}

int SetDlgState(HWND hwndDlg)
{
	TCHAR buff[10];

	EnableWindow(GetDlgItem(hwndDlg, IDC_BUT_BROWSE), ServiceExists( MS_FOLDERS_GET_PATH ) ? FALSE : TRUE );

	if ( new_options.backup_types == BT_DISABLED )
	{
		CheckDlgButton(hwndDlg, IDC_RAD_DISABLED, BST_CHECKED);
		EnableWindow(GetDlgItem(hwndDlg, IDC_ED_PERIOD), FALSE);
		EnableWindow(GetDlgItem(hwndDlg, IDC_PT), FALSE);

		CheckDlgButton(hwndDlg, IDC_RAD_START, BST_UNCHECKED);
		CheckDlgButton(hwndDlg, IDC_RAD_EXIT, BST_UNCHECKED);
		CheckDlgButton(hwndDlg, IDC_RAD_PERIODIC, BST_UNCHECKED);
	}
	else
	{
		EnableWindow(GetDlgItem(hwndDlg, IDC_ED_PERIOD), new_options.backup_types & BT_PERIODIC);
		EnableWindow(GetDlgItem(hwndDlg, IDC_PT), new_options.backup_types & BT_PERIODIC);

		CheckDlgButton(hwndDlg, IDC_RAD_DISABLED, BST_UNCHECKED);
		CheckDlgButton(hwndDlg, IDC_RAD_START, new_options.backup_types & BT_START ? BST_CHECKED : BST_UNCHECKED);
		CheckDlgButton(hwndDlg, IDC_RAD_EXIT, new_options.backup_types & BT_EXIT ? BST_CHECKED : BST_UNCHECKED);
		CheckDlgButton(hwndDlg, IDC_RAD_PERIODIC, new_options.backup_types & BT_PERIODIC ? BST_CHECKED : BST_UNCHECKED);
	}

	SendDlgItemMessage(hwndDlg, SPIN_PERIOD, UDM_SETRANGE32, (WPARAM)1, (LPARAM)60);
	if ( _itot_s( new_options.period, buff, SIZEOF( buff ), 10) == 0 )
		SetDlgItemText(hwndDlg, IDC_ED_PERIOD, buff);

	SendDlgItemMessage(hwndDlg, SPIN_NUMBACKUPS, UDM_SETRANGE32, (WPARAM)1, (LPARAM)100);
	if ( _itot_s( new_options.num_backups, buff, SIZEOF( buff ), 10) == 0 )
		SetDlgItemText(hwndDlg, IDC_ED_NUMBACKUPS, buff);

	SetDlgItemText(hwndDlg, IDC_ED_FOLDER, new_options.folder);

	CheckDlgButton(hwndDlg, IDC_CHK_NOPOPUP, new_options.disable_popups ? BST_CHECKED : BST_UNCHECKED);

	return 0;
}

int CALLBACK BrowseProc(HWND hwnd,UINT uMsg, LPARAM lParam, LPARAM lpData)
{
	TCHAR* folder;
    switch(uMsg)
    {
        case BFFM_INITIALIZED:
			folder = Utils_ReplaceVarsT(options.folder);
			SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)folder);
			mir_free(folder);
            break;
    }
	lParam;
	lpData;
    return 0;
}

void GetFolder(HWND hwndDlg, LPTSTR folder_buff, LPTSTR backupfolder)
{
	GetDlgItemText( hwndDlg, IDC_ED_FOLDER, folder_buff, MAX_PATH );

	if ( ! *folder_buff )
		_tcscpy_s( folder_buff, MAX_PATH, DIR SUB_DIR );

	LPCTSTR tmp = Utils_ReplaceVarsT( folder_buff );
	if ( _tcslen( tmp ) >= 2 && ( tmp[1] == ':' || ( tmp[0] == '\\' && tmp[1] == '\\' ) ) )
		_tcsncpy_s( backupfolder, MAX_PATH, tmp, MAX_PATH - 1 );
	else
	{
		LPCTSTR profileDir = Utils_ReplaceVarsT( _T("%miranda_profile%") );
		mir_sntprintf( backupfolder, MAX_PATH, _T("%s\\%s"), profileDir, tmp );
		mir_free( (void*)profileDir );

		mir_sntprintf( folder_buff, MAX_PATH, _T("%s\\%s"), _T("%miranda_profile%"), tmp );
	}
	mir_free( (void*)tmp );
}

INT_PTR CALLBACK DlgProcOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	TCHAR buff[10];
	TCHAR folder_buff[MAX_PATH] = {0}, backupfolder[MAX_PATH] = {0};
	TCHAR tszTooltipText[1024];
	BROWSEINFO bi;
	LPCITEMIDLIST pidl;
	OPENOPTIONSDIALOG ood = {0};

	switch ( msg )
	{
	case WM_INITDIALOG:
		TranslateDialogDefault( hwndDlg );
		memcpy(&new_options, &options, sizeof(Options));

		if (ServiceExists(MS_FOLDERS_GET_PATH))
		{
			ShowWindow(GetDlgItem(hwndDlg, IDC_ED_FOLDER), SW_HIDE);
			ShowWindow(GetDlgItem(hwndDlg, IDC_LNK_FOLDERS), SW_SHOW);
		}
		else
		{
			ShowWindow(GetDlgItem(hwndDlg, IDC_ED_FOLDER), SW_SHOW);
			ShowWindow(GetDlgItem(hwndDlg, IDC_LNK_FOLDERS), SW_HIDE);

			mir_sntprintf(tszTooltipText, SIZEOF(tszTooltipText), _T("%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s"),
				_T("%miranda_path%"),			TranslateT("Path to root miranda folder"),
				_T("%miranda_profile%"),		TranslateT("Path to current miranda profile"),
				_T("%miranda_profilename%"),	TranslateT("Name of current miranda profile (filename, without extension)"),
				_T("%miranda_userdata%"),		TranslateT("Will return parsed string %miranda_profile%\\Profiles\\%miranda_profilename%"),
				_T("%appdata%"),				TranslateT("Same as environment variable %appdata% for currently logged-on Windows user"),
				_T("%username%"),				TranslateT("Username for currently logged-on Windows user"),
				_T("%mydocuments%"),			TranslateT("My Documents folder for currently logged-on Windows user"),
				_T("%desktop%"),				TranslateT("Desktop folder for currently logged-on Windows user"),
				_T("%xxxxxxx%"),				TranslateT("Any environment variable defined in current Windows session (like %systemroot%, %allusersprofile%, etc.)")
				);
			hPathTip = CreateToolTip(GetDlgItem(hwndDlg, IDC_ED_FOLDER), tszTooltipText, TranslateT("Variables"));
		}

		SetDlgState(hwndDlg);

		SendMessage(GetDlgItem(hwndDlg, IDC_PT), CB_ADDSTRING, 0, (LPARAM) TranslateT("Days"));
		SendMessage(GetDlgItem(hwndDlg, IDC_PT), CB_ADDSTRING, 0, (LPARAM) TranslateT("Hours"));
		SendMessage(GetDlgItem(hwndDlg, IDC_PT), CB_ADDSTRING, 0, (LPARAM) TranslateT("Minutes"));
		switch(new_options.period_type){
			case PT_DAYS: SendDlgItemMessage(hwndDlg, IDC_PT, CB_SETCURSEL, 0, 0); break;
			case PT_HOURS: SendDlgItemMessage(hwndDlg, IDC_PT, CB_SETCURSEL, 1, 0); break;
			case PT_MINUTES: SendDlgItemMessage(hwndDlg, IDC_PT, CB_SETCURSEL, 2, 0); break;
		}
		if (hPathTip)
			SetTimer(hwndDlg, 0, 3000, NULL);
		return TRUE;

	case WM_COMMAND:
		if ( HIWORD( wParam ) == EN_CHANGE && ( HWND )lParam == GetFocus())
		{
			switch( LOWORD( wParam ))
			{
			case IDC_ED_PERIOD:
			case IDC_ED_FOLDER:
			case IDC_ED_NUMBACKUPS:
				SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
			}
		}
		if ( HIWORD( wParam ) == CBN_SELCHANGE)
		{
			SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
		}
		if ( HIWORD( wParam ) == BN_CLICKED )
		{
			switch( LOWORD( wParam ))
			{
			case IDC_RAD_DISABLED:
				if(IsDlgButtonChecked(hwndDlg, IDC_RAD_DISABLED)) {
					new_options.backup_types = BT_DISABLED;
				}
				SetDlgState(hwndDlg);
				SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
				break;

			case IDC_RAD_START:
				if(IsDlgButtonChecked(hwndDlg, IDC_RAD_START))
					new_options.backup_types |= BT_START;
				else
					new_options.backup_types &= ~BT_START;
				SetDlgState(hwndDlg);
				SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
				break;

			case IDC_RAD_EXIT:
				if(IsDlgButtonChecked(hwndDlg, IDC_RAD_EXIT))
					new_options.backup_types |= BT_EXIT;
				else
					new_options.backup_types &= ~BT_EXIT;
				SetDlgState(hwndDlg);
				SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
				break;

			case IDC_RAD_PERIODIC:
				if(IsDlgButtonChecked(hwndDlg, IDC_RAD_PERIODIC))
					new_options.backup_types |= BT_PERIODIC;
				else
					new_options.backup_types &= ~BT_PERIODIC;
				SetDlgState(hwndDlg);
				SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
				break;

			case IDC_BUT_OPEN:
				GetFolder( hwndDlg, folder_buff, backupfolder );
				ShellExecute( hwndDlg, NULL, backupfolder, NULL, _T(""), SW_SHOWNORMAL );
				break;

			case IDC_BUT_BROWSE:
				GetFolder( hwndDlg, folder_buff, backupfolder );
				bi.hwndOwner = hwndDlg;
				bi.pidlRoot = 0;
				bi.pszDisplayName = backupfolder;
				bi.lpszTitle = TranslateT("Select backup folder:");
				bi.ulFlags = BIF_USENEWUI | BIF_RETURNONLYFSDIRS | BIF_SHAREABLE;
				bi.lpfn = BrowseProc;
				bi.lParam = 0;
				bi.iImage = 0;
				if((pidl = SHBrowseForFolder(&bi)) != 0)
				{
					SHGetPathFromIDList(pidl, folder_buff);
					ShortenPath( folder_buff );
					SetDlgItemText(hwndDlg, IDC_ED_FOLDER, folder_buff);
					SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
					CoTaskMemFree((void *)pidl);
				}
				break;

			case IDC_BUT_NOW:
				{
					BOOL old = options.disable_popups;
					options.disable_popups = FALSE;
					Backup( NULL );
					options.disable_popups = old;
				}
				break;

			case IDC_CHK_NOPOPUP:
				new_options.disable_popups = IsDlgButtonChecked(hwndDlg, IDC_CHK_NOPOPUP);
				SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
				break;

			case IDC_LNK_FOLDERS:
				ood.cbSize = sizeof(ood);
				ood.pszGroup = "Customize";
				ood.pszPage = "Folders";
				CallService( MS_OPT_OPENOPTIONS, 0, (LPARAM)&ood );
				break;
			}
		}

		break;

	case WM_TIMER:
		if(IsWindow(hPathTip))
			KillTimer(hPathTip, 4); // It will prevent tooltip autoclosing
		break;

	case WM_NOTIFY:
		if (((LPNMHDR)lParam)->code == PSN_APPLY )
		{
			GetDlgItemText(hwndDlg, IDC_ED_PERIOD, buff, SIZEOF(buff));
			new_options.period = max( 1, min( 60, _ttoi( buff ) ) );
			GetDlgItemText(hwndDlg, IDC_ED_NUMBACKUPS, buff, SIZEOF(buff));
			new_options.num_backups = max( 1, min( 100, _ttoi( buff ) ) );

			switch(SendDlgItemMessage(hwndDlg, IDC_PT, CB_GETCURSEL, 0, 0))
			{
				case 0: new_options.period_type = PT_DAYS; break;
				case 1: new_options.period_type = PT_HOURS; break;
				case 2: new_options.period_type = PT_MINUTES; break;
			}

			GetFolder( hwndDlg, folder_buff, backupfolder );
			{
				BOOL folder_ok = TRUE;

				if ( SHPathPrepareForWrite( hwndDlg, NULL, backupfolder, SHPPFW_DIRCREATE ) != S_OK )
				{
					TCHAR szMsg[ 200 ];
					_tcscpy_s( szMsg, SIZEOF( szMsg ), TranslateT("Error creating backup folder:") );
					_tcscat_s( szMsg, SIZEOF( szMsg ), _T("\r\n") );
					PathCompactPathEx( szMsg + _tcslen( szMsg ), backupfolder, (UINT)( SIZEOF( szMsg ) - _tcslen( szMsg ) - 1 ), 0 );
					ShowPopup( szMsg, MB_ICONERROR );
					folder_ok = FALSE;
				}

				if ( folder_ok )
				{
					_tcsncpy_s( new_options.folder, MAX_PATH, folder_buff, MAX_PATH - 1 );
					memcpy( &options, &new_options, sizeof( Options ) );

					SaveOptions();

					// in case of settings was changed by SaveOptions() function
					memcpy( &new_options, &options, sizeof( Options ) );
					SetDlgState( hwndDlg );

					SetBackupTimer();

					SetWindowLongPtr( hwndDlg, 0 /*DWL_MSGRESULT*/, PSNRET_NOERROR );
					return TRUE;
				}
			}
			SetWindowLongPtr( hwndDlg, 0 /*DWL_MSGRESULT*/, PSNRET_INVALID_NOCHANGEPAGE );
			return FALSE;

		}
		break;

		case WM_DESTROY:
			if (hPathTip)
			{
				KillTimer(hwndDlg, 0);
				DestroyWindow(hPathTip);
				hPathTip = 0;
			}
			return FALSE;
	}

	return FALSE;
}

int OptionsInit(WPARAM wParam, LPARAM /*lParam*/)
{
	OPTIONSDIALOGPAGE odp = {};

	odp.cbSize						= sizeof(odp);
	odp.position					= -790000000;
	odp.hInstance					= hInst;
	odp.pszTemplate					= MAKEINTRESOURCEA(IDD_OPTIONS);
	odp.ptszTitle					= LPGENT("Database Backups");
	odp.ptszGroup					= LPGENT("Services");
	odp.flags						= ODPF_BOLDGROUPS | ODPF_TCHAR;
	odp.pfnDlgProc					= DlgProcOptions;
	CallService( MS_OPT_ADDPAGE, wParam,( LPARAM )&odp );

	return 0;
}
